home *** CD-ROM | disk | FTP | other *** search
/ APDL Other Worlds / APDL Other Worlds Collection.iso / SF3000 / Extras / !SFtoSpr / c / Main next >
Encoding:
Text File  |  2003-11-06  |  12.6 KB  |  403 lines

  1. /*
  2.  *  SFtoSpr - Star Fighter 3000 graphics converter
  3.  *  Main application skeleton
  4.  *  Copyright (C) 2000  Chris Bazley
  5.  *
  6.  *  This program is free software; you can redistribute it and/or modify
  7.  *  it under the terms of the GNU General Public Licence as published by
  8.  *  the Free Software Foundation; either version 2 of the Licence, or
  9.  *  (at your option) any later version.
  10.  *
  11.  *  This program is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *  GNU General Public Licence for more details.
  15.  *
  16.  *  You should have received a copy of the GNU General Public Licence
  17.  *  along with this program; if not, write to the Free Software
  18.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  */
  20.  
  21. /* ANSI library files */
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <stdbool.h>
  25. #include <signal.h>
  26. #include <ctype.h>
  27. #include <stdio.h>
  28.  
  29. /* RISC OS library files */
  30. #include "kernel.h"
  31. #include "toolbox.h"
  32. #include "event.h"
  33. #include "flex.h"
  34. #include "wimp.h"
  35. #include "wimplib.h"
  36.  
  37. /* My library files */
  38. #include "err.h"
  39. #include "msgtrans.h"
  40. #include "hourglass.h"
  41. #include "Macros.h"
  42. #include "Loader.h"
  43. #include "SFformats.h"
  44. #include "ViewsMenu.h"
  45. #include "RoundRobin.h"
  46. #include "InputFocus.h"
  47. #include "nobudge.h"
  48.  
  49. /* Local headers */
  50. #include "SFIconbar.h"
  51. #include "SFgfxconv.h"
  52. #include "Scan.h"
  53. #include "Utils.h"
  54. #include "Main.h"
  55. #include "SFMenu.h"
  56. #include "PreQuit.h"
  57.  
  58. #define WimpVersion    310
  59.  
  60. /* This is the MINIMUM amount of work we do per null poll (Since our
  61.    RoundRobinHandler isn't very well written, the maximum time slice is
  62.    this PLUS the time to convert, load or save the largest file). We
  63.    null poll as often as possible, like a program running under the
  64.    TaskWindow module. The event mask is used (rather than
  65.    Wimp_PollIdle) to avoid receiving unnecessarily null events. */
  66. #define NULL_TIME_SLICE 10
  67.  
  68. _kernel_oserror shared_err_block = {255, ""};
  69. bool verify_spriteareas;
  70. char taskname[32];
  71. int wimp_version;
  72. bool multi_saveboxes = false;
  73. bool quit_parse_cl = false;
  74. bool output_new_format = false;
  75. int timeslice = NULL_TIME_SLICE;
  76. ObjectId last_savebox = NULL_ObjectId;
  77.  
  78. static WimpPollBlock poll_block;
  79. static IdBlock       id_block;
  80.  
  81. /* ----------------------------------------------------------------------- */
  82. /*                       Function prototypes                               */
  83.  
  84. static WimpMessageHandler WimpPreQuit_handler, WimpQuit_handler;
  85. static ToolboxEventHandler autocreate_handler, error_handler;
  86. static void initialise(void);
  87. static void process_arguments(int argc, char *argv[]);
  88. static void load_cl_files(int argc, char *argv[]);
  89. static LoaderFinishedHandler display_tiles, display_planets;
  90. static void simple_exit(_kernel_oserror *e);
  91.  
  92. /* ----------------------------------------------------------------------- */
  93. /*                         Public functions                                */
  94.  
  95. int main(int argc, char *argv[])
  96. {
  97.   process_arguments(argc, argv);
  98.   initialise();
  99.   load_cl_files(argc, argv);
  100.   if(quit_parse_cl)
  101.     WimpQuit_handler(NULL, NULL);
  102.  
  103.   /*
  104.    * poll loop
  105.    */
  106.  
  107.   while (TRUE) {
  108.     int event_code;
  109.     event_poll (&event_code, &poll_block, NULL);
  110.   }
  111. }
  112.  
  113. /* ----------------------------------------------------------------------- */
  114. /*                         Private functions                               */
  115.  
  116. static int WimpPreQuit_handler(WimpMessage *message, void *handle)
  117. {
  118.   int th;
  119.   if(message->hdr.size < 20 || message->data.words[0] == 0)
  120.     th = message->hdr.sender; /* shutdown in progress */
  121.   else
  122.     th = 0; /* just our task */
  123.  
  124.   /* If function returns false then unsaved data */
  125.   if(!TRY_QUIT(th)) {
  126.     /* Object by acknowledging message */
  127.     message->hdr.your_ref = message->hdr.my_ref;
  128.     RE(wimp_send_message(Wimp_EUserMessageAcknowledge, message, message->hdr.sender, NULL, NULL));
  129.   }
  130.   return 1; /* claim event */
  131. }
  132.  
  133. /* ----------------------------------------------------------------------- */
  134.  
  135. static int WimpQuit_handler(WimpMessage *message,void *handle)
  136. {
  137.   exit(EXIT_SUCCESS);
  138.   return 1; /* claim event */
  139. }
  140.  
  141. /* ----------------------------------------------------------------------- */
  142.  
  143. static int autocreate_handler(int event_code, ToolboxEvent *event, IdBlock *id_block, void *handle)
  144. {
  145.   /* Catch auto-created objects and initialise handlers etc. */
  146.   ToolboxObjectAutoCreatedEvent *toace = (ToolboxObjectAutoCreatedEvent *)event;
  147.  
  148.   if(strcmp(toace->template_name, "Menu") == 0) {
  149.     Menu_initialise(id_block->self_id);
  150.     return 1; /* claim event */
  151.   }
  152.   if (strcmp(toace->template_name, "PreQuit") == 0) {
  153.     PreQuit_initialise(id_block->self_id);
  154.     return 1; /* claim event */
  155.   }
  156.   if (strcmp(toace->template_name, "Iconbar") == 0) {
  157.     Iconbar_initialise(id_block->self_id);
  158.     return 1; /* claim event */
  159.   }
  160.   return 0; /* pass event on */
  161. }
  162.  
  163. /* ----------------------------------------------------------------------- */
  164.  
  165. static int error_handler(int event_code, ToolboxEvent *event, IdBlock *id_block, void *handle)
  166. {
  167.   ToolboxErrorEvent *totee = (ToolboxErrorEvent *)event;
  168.  
  169.   if(totee->errnum == 0x80b633 || totee->errnum == 0x131c3) /* "To save drag...", locked file */
  170.     err_report(totee->errnum, totee->errmess);
  171.   else
  172.     err_complain(totee->errnum, totee->errmess);
  173.  
  174.   return 1; /* claim event */
  175. }
  176.  
  177. /* ----------------------------------------------------------------------- */
  178.  
  179. static void initialise(void)
  180. {
  181.   int    toolbox_events = 0,
  182.          wimp_messages = 0;
  183.  
  184.   hourglass_on();
  185.  
  186.   /*
  187.    * Prevent termination on SIGINT (we use the escape key ourselves)
  188.    */
  189.    signal(SIGINT, SIG_IGN);
  190.  
  191.   /*
  192.    * register ourselves with the Toolbox.
  193.    */
  194.  
  195.   {
  196.     _kernel_oserror *e = toolbox_initialise (0, WimpVersion, &wimp_messages, &toolbox_events, "<SFtoSprRes$Dir>",msgs_get_descriptor(), &id_block, &wimp_version, 0, 0);
  197.     if(e != NULL)
  198.       simple_exit(e);
  199.   }
  200.  
  201.   strncpy(taskname, msgs_lookup("_TaskName"), sizeof(taskname)-1);
  202.   err_set_taskname(taskname, (wimp_version >= 321));
  203.  
  204.   /*
  205.    * initialise the flex library
  206.    */
  207.  
  208.   flex_init(taskname, (int *)msgs_get_descriptor(), 0); /* (use Wimpslot and own messages file) */
  209.   flex_set_budge(1); /* allow budging of flex when heap extends */
  210.  
  211.   /*
  212.    * initialise the event library.
  213.    */
  214.  
  215.   event_initialise (&id_block);
  216.   event_set_mask (Wimp_Poll_NullMask |
  217.                   Wimp_Poll_PointerLeavingWindowMask |
  218.                   Wimp_Poll_PointerEnteringWindowMask |
  219.                   Wimp_Poll_KeyPressedMask | /* Dealt with by Toolbox */
  220.                   Wimp_Poll_LoseCaretMask |
  221.                   Wimp_Poll_GainCaretMask);
  222.  
  223.   EF(event_register_toolbox_handler(-1, Toolbox_ObjectAutoCreated, autocreate_handler, 0));
  224.   EF(event_register_toolbox_handler(-1, Toolbox_Error, error_handler, 0));
  225.   EF(event_register_message_handler(Wimp_MPreQuit, WimpPreQuit_handler, 0));
  226.   EF(event_register_message_handler(Wimp_MQuit, WimpQuit_handler, 0));
  227.  
  228.   EF(InputFocus_initialise());
  229.   EF(RoundRobin_initialise(timeslice));
  230.  
  231.   /*
  232.    * Initialise other components.
  233.    */
  234.  
  235.   EF(loader_initialise(0));
  236.  
  237.   /* Capture Filer double-clicks of MapTiles/Planets and act separately from drags to app icon */
  238.   EF(loader_register_listener(LISTENER_CLAIM, FILETYPE_MAPTILES, NULL, NULL, load_compressed, display_tiles, NULL));
  239.   EF(loader_register_listener(LISTENER_CLAIM, FILETYPE_PLANETS, NULL, NULL, load_compressed, display_planets, NULL));
  240.  
  241.   /* Check for SpriteExtend 0.99 (can we verify SAs?) */
  242.   EF(_kernel_setenv("SFtoSpr$Verify","1"));
  243.   if(_kernel_oscli("RMEnsure SpriteExtend 0.99 Set SFtoSpr$Verify 0") == _kernel_ERROR)
  244.     err_check_fatal_rep(_kernel_last_oserror());
  245.   {
  246.     char readvar_buffer[16];
  247.     EF(_kernel_getenv("SFtoSpr$Verify", readvar_buffer, sizeof(readvar_buffer)));
  248.     verify_spriteareas = (strcmp(readvar_buffer, "1") == 0);
  249.     EF(_kernel_setenv("SFtoSpr$Verify",NULL));
  250.   }
  251.  
  252.   EF(ViewsMenu_create());
  253.  
  254.   hourglass_off();
  255. }
  256.  
  257. /* ----------------------------------------------------------------------- */
  258.  
  259. static void load_cl_files(int argc, char *argv[])
  260. {
  261.   /*
  262.    * Load any files specified as command-line arguments
  263.    */
  264.  
  265.   for(int i = 1; i < argc; i++) {
  266.     /* anything without a '-' in front is interpreted as a file to load */
  267.     if (*argv[i] != '-' && (i < 2 || !ViewsMenu_strcmp_nc(argv[i-1], "-timeslice"))) {
  268.  
  269.       /* get filetype (can't use _kernel_osfile as it doesn't return R6) */
  270.       _kernel_swi_regs regs;
  271.       regs.r[0] = 23;
  272.       regs.r[1] = (int)argv[i];
  273.       if(!E(_kernel_swi(OS_File, ®s, ®s))) {
  274.         _kernel_oserror *err;
  275.         void *cl_buffer;
  276.  
  277.         switch(regs.r[6]) {
  278.           case FILETYPE_MAPTILES:
  279.             err = load_compressed(argv[i], (flex_ptr)&cl_buffer);
  280.             if(err == NULL)
  281.               display_tiles(argv[i], 1, (flex_ptr)&cl_buffer, FILETYPE_MAPTILES, NULL);
  282.             else {
  283.               err_complain(0, msgs_lookup_sub1("LoadFail", err->errmess));
  284.               flex_free((flex_ptr)&cl_buffer);
  285.             }
  286.             break;
  287.  
  288.           case FILETYPE_PLANETS:
  289.             err = load_compressed(argv[i], (flex_ptr)&cl_buffer);
  290.             if(err == NULL)
  291.               display_planets(argv[i], 1, (flex_ptr)&cl_buffer, FILETYPE_PLANETS, NULL);
  292.             else {
  293.               err_complain(0, msgs_lookup_sub1("LoadFail", err->errmess));
  294.               flex_free((flex_ptr)&cl_buffer);
  295.             }
  296.             break;
  297.         }
  298.       } /* got filetype OK */
  299.     } /* parameter is filename */
  300.   } /* next parameter */
  301. }
  302.  
  303. /* ----------------------------------------------------------------------- */
  304.  
  305. static void simple_exit(_kernel_oserror *e)
  306. {
  307.   /* Limited amount we can do with no messages file... */
  308.   wimp_report_error(e, Wimp_ReportError_Cancel, "SFtoSpr");
  309.   exit(EXIT_FAILURE);
  310. }
  311.  
  312. /* ----------------------------------------------------------------------- */
  313.  
  314. static void process_arguments(int argc, char *argv[])
  315. {
  316.   /*
  317.    * Look at command-line parameters
  318.    */
  319.  
  320.   for(int i = 1; i < argc; i++) {
  321.     if(ViewsMenu_strcmp_nc(argv[i], "-quit"))
  322.       quit_parse_cl = true;
  323.     else {
  324.       if(ViewsMenu_strcmp_nc(argv[i], "-multi"))
  325.         multi_saveboxes = true;
  326.       else {
  327.         if(ViewsMenu_strcmp_nc(argv[i], "-newformat"))
  328.           output_new_format = true;
  329.         else {
  330.           if(ViewsMenu_strcmp_nc(argv[i], "-timeslice") && i+1 < argc) {
  331.             for(int c = 0; c < strlen(argv[i+1]); c++) {
  332.               if(!isdigit(argv[i+1][c])) {
  333.                 strcpy(shared_err_block.errmess, "Bad command line parameters");
  334.                 simple_exit(&shared_err_block);
  335.               }
  336.             }
  337.             sscanf(argv[i+1], "%d", ×lice);
  338.           } else {
  339.             if(*argv[i] == '-') {
  340.               /* Catches unknown options, but not time values or file paths */
  341.               strcpy(shared_err_block.errmess, "Bad command line parameters");
  342.               simple_exit(&shared_err_block);
  343.             }
  344.           }
  345.         }
  346.       }
  347.     }
  348.   }
  349. }
  350.  
  351. /* ----------------------------------------------------------------------- */
  352.  
  353. static void display_tiles(char *file_path, bool data_saved, flex_ptr buffer, int filetype,  void *handle)
  354. {
  355.   /* Deal with Filer double-clicks on MapTiles files */
  356.  
  357.   /* convert to sprites */
  358.   spriteareaheader *sprite_area;
  359.   if(tiles_to_sprites((SF_MapTilesSetHdr **)buffer, &sprite_area)) {
  360.  
  361.     /* save spritefile to !Scrap */
  362.     nobudge_register(256);
  363.     _kernel_oserror *err = _swix(OS_SpriteOp, _INR(0,2), SPRITEOP_SAVE_AREA+SPRITEOP_USERAREA_SPRNAME, sprite_area, "<Wimp$Scrap>");
  364.     nobudge_deregister();
  365.     if(err != NULL)
  366.       err_report(err->errnum, msgs_lookup_sub1("SaveFail", err->errmess));
  367.     else {
  368.        /* open spritefile (in Paint?) */
  369.       if(_kernel_oscli("Filer_Run <Wimp$Scrap>") == _kernel_ERROR)
  370.         err_check_rep(_kernel_last_oserror());
  371.     }
  372.     flex_free((flex_ptr)&sprite_area);
  373.   }
  374.   flex_free(buffer);
  375. }
  376.  
  377. /* ----------------------------------------------------------------------- */
  378.  
  379. static void display_planets(char *file_path, bool data_saved, flex_ptr buffer, int filetype, void *handle)
  380. {
  381.   /* Deal with Filer double-clicks on Planets files */
  382.   spriteareaheader *sprite_area;
  383.   _kernel_oserror *err;
  384.  
  385.    /* convert to sprites */
  386.    if(planets_to_sprites((SF_PlanetsSetHdr **)buffer, &sprite_area)) {
  387.  
  388.      /* save spritefile to !Scrap */
  389.     nobudge_register(256);
  390.     err = _swix(OS_SpriteOp, _INR(0,2), SPRITEOP_SAVE_AREA+SPRITEOP_USERAREA_SPRNAME, sprite_area, "<Wimp$Scrap>");
  391.     nobudge_deregister();
  392.     if(err != NULL)
  393.       err_report(err->errnum, msgs_lookup_sub1("SaveFail", err->errmess));
  394.     else {
  395.        /* open spritefile (in Paint?) */
  396.        if(_kernel_oscli("Filer_Run <Wimp$Scrap>") == _kernel_ERROR)
  397.          err_check_rep(_kernel_last_oserror());
  398.      }
  399.      flex_free((flex_ptr)&sprite_area);
  400.    }
  401.    flex_free(buffer);
  402. }
  403.